package com.threeti.mecool.web.controller.admin;

import com.threeti.mecool.core.application.Cache;
import com.threeti.mecool.core.application.acl.UserService;
import com.threeti.mecool.core.application.basicdata.BasicDataSyncService;
import com.threeti.mecool.core.application.plan.PlanService;
import com.threeti.mecool.core.domain.model.acl.PermissionRole;
import com.threeti.mecool.core.domain.model.acl.PermissionRoleAchievement;
import com.threeti.mecool.core.domain.model.acl.User;
import com.threeti.mecool.core.domain.model.basicdata.biz.ChannelSync;
import com.threeti.mecool.core.domain.model.plan.UserStepResult;
import com.threeti.mecool.core.domain.model.plan.WorkFlowConst;
import com.threeti.mecool.core.infrastructure.persistence.acl.PermRoleRepository;
import com.threeti.mecool.core.infrastructure.persistence.acl.PermissionRoleAchievementRepository;
import com.threeti.mecool.core.infrastructure.persistence.acl.UserRepository;
import com.threeti.mecool.core.infrastructure.persistence.basicdata.biz.ChannelSyncRepository;
import com.threeti.mecool.core.infrastructure.persistence.plan.JobRepository;
import com.threeti.mecool.core.infrastructure.persistence.project.ProjectCategoryRepository;
import com.threeti.mecool.framework.util.PageHandler;
import com.threeti.mecool.legacy.domain.model.basicdata.biz.PosLegacy;
import com.threeti.mecool.legacy.infrastructure.persistence.PosLegacyRepository;
import com.threeti.mecool.web.assembler.PermissionRoleAchievementAssembler;
import com.threeti.mecool.web.assembler.UserAssembler;
import com.threeti.mecool.web.assembler.UserStepResultAssembler;
import com.threeti.mecool.web.form.ChannelInfoForm;
import com.threeti.mecool.web.form.PermissionRoleForm;
import com.threeti.mecool.web.form.UserForm;
import com.threeti.mecool.web.util.RequestUtil;
import com.threeti.mecool.web.util.WebResponse;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
public class AdminConfigurationController {
    public static final Logger logger = LoggerFactory.getLogger(AdminConfigurationController.class);

    @Autowired
    Cache cache;

    //<editor-fold desc="fields">
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserService userService;

    @Autowired
    private PermRoleRepository permRoleRepo;

    @Autowired
    private JobRepository jobRepository;

    @Autowired
    private PermissionRoleAchievementRepository permissionRoleAchievementRepository;

    @Autowired
    private ProjectCategoryRepository projectCatRepo;

    @Autowired
    private PosLegacyRepository posRepo;

    @Autowired
    private BasicDataSyncService basicDataSyncService;

//    private ExecutorService executorService = Executors.newFixedThreadPool(4);

    @Autowired
    private PlanService planService;

//  @Autowired
//  private PermissionAclService aclService;

    @Autowired
    UserRepository userRepo;

    @Autowired
    private ChannelSyncRepository channelSyncRepository;
    //</editor-fold>

    @RequestMapping("/start.html")
    public String loginCallback(Principal principal) {
        logger.debug("USER_LOGIN: [{}] at: [{}]", principal.getName(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        cache.removeByPrefix("advancedSubordinateIdentitiesOfUser" + ":" + principal.getName() + ":");
        cache.remove("getProjectCodeLoginNameDisplayName_subOf" + ":" + userRepo.findByloginName(principal.getName()).getEmployee().getEmpId());
//        executorService.execute(new Runnable() {
//            @Override public void run() {
//                User user = userRepo.findWithPermissionRoleAndEntries(userService.getUserFromSession().getLoginName());
//                planService.advancedSubordinateIdentitiesOfUser(user, true);
//                planService.advancedSubordinateIdentitiesOfUser(user, false);
//            }
//        });
        return "/start";
    }

    @RequestMapping(value = "/userList.html")
    public String userList(Map modelMap) {
        modelMap.put("roles", permRoleRepo.findAllWithPermissionEntries());
        return "/admin/userList";
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/userListData.html")
    public String userListData(Pageable pageable, Map modelMap, HttpServletRequest request) {
        try {
            Map<String, String> paramMap = RequestUtil.getParameterMap(request);
            Page<User> users = userRepository.findAll(UserAssembler.toCriteria(paramMap), pageable);
            PageHandler p = new PageHandler(pageable.getPageNumber(),
                    Long.valueOf(users.getTotalElements()).intValue(),
                    pageable.getPageSize(),
                    users.getContent());
            modelMap.put("page", p);
            return "/admin/userListData";
        } catch (Exception e) {
            return null;
        }
    }

    @SuppressWarnings({"rawtypes"})
    @RequestMapping(value = "/removeUser.html")
    public String removeUser(@RequestParam(required = true) Long userId, Map modelMap) {

        try {
            userService.removeUserFromSystem(userRepository.findOne(userId));
            return "/admin/userList";
        } catch (Exception e) {
            e.printStackTrace();
            return "/admin/userList";
        }
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/beforeEditUser.html")
    public String beforeEditUser(@RequestParam(required = true) long userid, UserForm userForm, Map modelMap) {
        try {
            User user = userRepository.findOne(userid);
            modelMap.put("user", user);
            modelMap.put("roles", permRoleRepo.findAll());
            userForm.setRoleIdSlt(user.getPermissionRole().getId().toString());
            return "/admin/editUserForm";

        } catch (Exception e) {
            e.printStackTrace();
            return "/admin/userList";
        }
    }

    @RequestMapping(value = "/editUserForm.html")
    public String beforeEditUser(UserForm userForm, Map modelMap) {
        try {
            User userWithDataNeedToBeUpdated = UserAssembler.toDomWithPermissionEntries(userForm, permRoleRepo);
            userService.updateUserBy(Long.valueOf(userForm.getUpdatekey()), Long.valueOf(userForm.getOldRoleId()), userWithDataNeedToBeUpdated);

            WebResponse.newInstance().buildModelMapData(modelMap);

        } catch (Exception e) {
            logger.error("帐号维护异常", e);
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);
        }
        // return "redirect:/beforeEditUser.html?userid="+userForm.getUpdatekey();
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @SuppressWarnings({"rawtypes"})
    @RequestMapping(value = "/newPermissionRole.html")
    public String newPermissionRole(PermissionRoleForm permissionRoleForm, Map modelMap) {

        try {
//            PermissionRole permissionRole = new PermissionRole(permissionRoleForm.getName());
//            permissionRole.setPermissionEntries(permissionRoleForm.getPermissionEntries());
//            permissionRole.setAdvanced("1".equals(permissionRoleForm.getIsAdvanced()));
            PermissionRole role = UserAssembler.toDom(permissionRoleForm);
            role.setId(null);
            permRoleRepo.saveAndFlush(role);
            cache.removeByPrefix(String.format("PERM_ENTRY:%d:", role.getId()));

            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);
            e.printStackTrace();
        }

        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/roleList.html")
    public String roleList(PermissionRoleForm permissionRoleForm, Map modelMap) {
        List<PermissionRole> roles = permRoleRepo.findAllWithPermissionEntries();
        Collections.sort(roles, new Comparator<PermissionRole>() {
            @Override
            public int compare(PermissionRole o1, PermissionRole o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        modelMap.put("roles", roles);
        return "admin/roleList";
    }

    @SuppressWarnings("rawtypes")
    @RequestMapping(value = "/editPermissionRole.html")
    public String editPermissionRole(PermissionRoleForm permissionRoleForm, Map modelMap) {

        try {
            PermissionRole role = UserAssembler.toDom(permissionRoleForm);
            //aclService.renewAllTheAclsRelatedByPermissionRole(role);

            permRoleRepo.saveAndFlush(role);
            cache.removeByPrefix(String.format("PERM_ENTRY:%d:", role.getId()));

            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            logger.error("修改角色权限异常", e);
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);
        }


        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }


    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(value = "/admin/newRoleTaskForm.html")
    public void newRoleTaskForm(Map modelMap) {
        modelMap.put("roles", permRoleRepo.findAllWithPermissionEntries());
    }

    @SuppressWarnings("rawtypes")
    @ResponseBody
    @RequestMapping(value = "/admin/newRoleTask.html")
    public String newRoleTask(@RequestBody ArrayList<Map> data) {
        try {
            for (Map map : data) {
                PermissionRoleAchievement entity = new PermissionRoleAchievement();
                entity.setJob(jobRepository.findOne(Long.valueOf(map.get("jobId").toString())));
                entity.setPermissionRole(permRoleRepo.findOne(Long.valueOf(map.get("roleId").toString())));
                entity.setTargetCount(Integer.valueOf(map.get("targetCount").toString()).intValue());

                permissionRoleAchievementRepository.save(entity);
            }
            return "ok";
        } catch (Exception e) {
            logger.error("", e);
            return "failed";
        }
    }


    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/admin/roleTaskList.html")
    public void roleTaskList(Map modelMap) {
        modelMap.put("jobList", jobRepository.findAll());
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/admin/roleTaskListData.html")
    public void roleTaskList(Map modelMap,
                             Pageable pageable,
                             HttpServletRequest request) {


        Specification<PermissionRoleAchievement> spec = PermissionRoleAchievementAssembler.toCriteria(RequestUtil.getParameterMap(request));

        Page<PermissionRoleAchievement> page = permissionRoleAchievementRepository.findAll(spec, pageable);

        PageHandler p = new PageHandler(pageable.getPageNumber(), Long.valueOf(page.getTotalElements()).intValue(),
                pageable.getPageSize(), page.getContent());
        modelMap.put("page", p);
    }


    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/admin/roleTaskEdit.html")
    public void roleTaskEdit(Map modelMap, Long id) {
        modelMap.put("permissionRoleAchievement", permissionRoleAchievementRepository.findOne(id));
    }

    @RequestMapping(value = "/admin/editRoleTask.html")
    public String editRoleTask(Map modelMap,
                               Long id,
                               Integer targetCount,
                               Long jobId,
                               Long roleId) {

        try {
            PermissionRoleAchievement entity = permissionRoleAchievementRepository.findOne(id);
            entity.setJob(jobRepository.findOne(jobId));
            entity.setPermissionRole(permRoleRepo.findOne(roleId));
            entity.setTargetCount(targetCount);
            permissionRoleAchievementRepository.save(entity);

            WebResponse.newInstance()
                    .buildModelMapData(modelMap);
        } catch (Exception e) {
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);
        }

        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @RequestMapping(value = "/admin/storeMapList.html")
    public void storeMapList(ChannelInfoForm form) {
        form.setProjectCategories(projectCatRepo.findAll());
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/admin/storeMapListData.html")
    public void storeMapListData(ChannelInfoForm form, Pageable pageable, Map modelMap) {
        Page<UserStepResult> usrs = UserStepResult.findBySpec(UserStepResultAssembler.toCriteria(form, pageable), pageable);
        PageHandler p = new PageHandler(pageable.getPageNumber(), Long.valueOf(usrs.getTotalElements()).intValue(),
                pageable.getPageSize(), usrs.getContent());
        modelMap.put("page", p);
    }

    @RequestMapping(value = "/admin/storeList.html")
    public void storeList(ChannelInfoForm form) {
        form.setProjectCategories(projectCatRepo.findAll());
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/admin/storeListData.html")
    public void storeListData(ChannelInfoForm form, Pageable pageable, Map modelMap) {
        Page<UserStepResult> usrs = UserStepResult.findBySpec(UserStepResultAssembler.toCriteria(form, pageable), pageable);
        PageHandler p = new PageHandler(pageable.getPageNumber(), Long.valueOf(usrs.getTotalElements()).intValue(),
                pageable.getPageSize(), usrs.getContent());
        modelMap.put("page", p);
    }

    @RequestMapping("/maintenance/tablechannelsync.html")
    public void scs(Map<String, Object> map) {
        try {
//            basicDataSyncService.doSyncOfChannelSync();
            basicDataSyncService.synchronizeChannelSyncWithPos();
            map.put("err", 0);
        } catch (Exception e) {
            logger.error("sync error", e);
            map.put("err", 1);
        }
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/admin/storeChangeDetail/{storeChangeId}.html")
    public String storeChangeDetail(@PathVariable Long storeChangeId, Map modelMap) {
        modelMap.put("usr", UserStepResult.findByIdWithDataTypeCode(storeChangeId));
        return "/admin/storeChangeDetailForm";
    }

    @RequestMapping("/admin/doStoreMapChangeDetail.html")
    public String storeMapChange(ChannelInfoForm form, Map modelMap) {
        Long userStepResultId = form.getUserStepResultId();
        if (userStepResultId == null) {
            WebResponse.newInstance().setExceptionMsg(new RuntimeException("参数错误 - User Step Result ID")).buildModelMapData(modelMap);
            return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
        }
        String updateType = form.getUpdateType();
        UserStepResult userStepResult = UserStepResult.findOne(userStepResultId);
        if (ChannelInfoForm.TYPE_UPDATE_CHANNEL.equals(updateType)) {
            ChannelSync channelSync = channelSyncRepository.findByChannelCode(userStepResult.getStoreCode());
            if (channelSync != null) {
                channelSync.setLatitude(form.getLatitude());
                channelSync.setLongitude(form.getLongitude());
                channelSyncRepository.save(channelSync);
            }
            userStepResult.setGpsSyncStatus(UserStepResult.STORE_SYNC_DONE);
            userStepResult.save();
        } else if (ChannelInfoForm.TYPE_DISABLE_CHANNEL.equals(updateType)) {
            userStepResult.setGpsSyncStatus(UserStepResult.STORE_SYNC_OBSOLETE);
            userStepResult.save();
        } else {
            WebResponse.newInstance().setExceptionMsg(new RuntimeException("参数错误 - Update Type")).buildModelMapData(modelMap);
            return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
        }
        WebResponse.newInstance().buildModelMapData(modelMap);
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @RequestMapping(value = "/admin/doStoreChangeDetail.html")
    public String storeChange(ChannelInfoForm form, Map modelMap) {
        String channelCode = form.getUpdatekey();
        String dataToBeChanged = form.getDataToBeChanged();
        String dataTypeCode = form.getDataTypeCode();
        String updateType = form.getUpdateType();
        if (StringUtils.isBlank(channelCode)) {
            WebResponse.newInstance().setExceptionMsg(new RuntimeException("门店通路编码为空，无法更新")).buildModelMapData(modelMap);
            return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
        }
        try {
            PosLegacy posLeg = posRepo.findOne(channelCode);
            if (posLeg == null) {
                WebResponse.newInstance().setExceptionMsg(new RuntimeException("无法找到对应的门店通路")).buildModelMapData(modelMap);
                return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
            }
            UserStepResult userStepResult = UserStepResult.findOne(form.getUserStepResultId());
            if (ChannelInfoForm.TYPE_UPDATE_CHANNEL.equals(updateType)) {
                if (WorkFlowConst.CODE_WF_STEP_TYPE_STORE_ADDRESS.equals(dataTypeCode)) {
                    posLeg.setAddress(dataToBeChanged);
                    ChannelSync channelSync = channelSyncRepository.findByChannelCode(channelCode);
                    channelSync.setAddress(posLeg.getAddress());
                    channelSyncRepository.save(channelSync);
                    //TODO jay:pos linkman update
                } else if (WorkFlowConst.CODE_WF_STEP_TYPE_CONTACT_NAME.equals(dataTypeCode)) {

                } else if (WorkFlowConst.CODE_WF_STEP_TYPE_CONTACT_POSITION.equals(dataTypeCode)) {

                } else if (WorkFlowConst.CODE_WF_STEP_TYPE_CONTACT_WAY.equals(dataTypeCode)) {

                }
                userStepResult.setStoreSyncStatus(UserStepResult.STORE_SYNC_DONE);
            } else if (ChannelInfoForm.TYPE_DISABLE_CHANNEL.equals(updateType)) {
//                posLeg.setIsDisable(PosLegacy.DISABLE);
                userStepResult.setStoreSyncStatus(UserStepResult.STORE_SYNC_OBSOLETE);
            }
            posRepo.saveAndFlush(posLeg);
            userStepResult.save();
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            WebResponse.newInstance().setExceptionMsg(e).buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

}
